package com.photoeditor.demo.ui.widget.image;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;

import com.photoeditor.demo.model.image.gl.DecoderLoader;
import com.photoeditor.demo.model.image.gl.Future;
import com.photoeditor.demo.model.image.gl.FutureListener;
import com.photoeditor.demo.model.image.gl.ThreadPool;
import com.photoeditor.demo.model.image.util.Utils;
import com.photoeditor.demo.util.BitmapDecoder;
import com.photoeditor.demo.util.FetcherHolder;

/**
 * 里面有解析图片相关代码
 */
public class PreViewBitmap implements TileSource {

    private Bitmap mScreenBitmap;

    private Rect mBitmapRect;

    private Future<?> mTask;

    private Paint mPaint;

    private String mPath;

    private DecoderLoader mLoader;

    private PreViewBitmapJob<BitmapRegionDecoder> mJob = new PreViewBitmapJob<BitmapRegionDecoder>() {

        @Override
        public BitmapRegionDecoder run(ThreadPool.JobContext jc) {
            jc.setMode(ThreadPool.MODE_NONE);
            BitmapRegionDecoder decoder = null;
            decoder = FetcherHolder.getPreviewBitmapCache().getDecoderFormCache(path);
            if (decoder == null || decoder.isRecycled()) {
                try {
                    {
                        if (BitmapDecoder.isVaildImage(path)) {
                            decoder = BitmapRegionDecoder.newInstance(path, false);
                        }
                    }
                    FetcherHolder.getPreviewBitmapCache().addDecoderToCache(path, decoder);
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            } else {
                /**
                 * 仍然加到缓存中  让它放在最前面
                 */
                FetcherHolder.getPreviewBitmapCache().addDecoderToCache(path, decoder);
            }
            return decoder;
        }

    };

    private FutureListener<BitmapRegionDecoder> mFutureListener = new FutureListener<BitmapRegionDecoder>() {

        @Override
        public void onFutureDone(Future<BitmapRegionDecoder> future) {
            BitmapRegionDecoder decoder = future.get();
            if (decoder == null) {
                if (mListener != null) {
                    mListener.onDecodeOver(null, 0, 0, null);
                }
                return;
            }
            int width = decoder.getWidth();
            int height = decoder.getHeight();
            Bitmap bitmap = FetcherHolder.getPreviewBitmapCache().getBitmapFromCache(mPath);
            if (bitmap == null) {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = Utils.computeSampleSize(Utils.TARGET_SIZE * 1.0f / Math.max(width, height));
                int duration = 0;
                long time = System.currentTimeMillis();
                bitmap = decoder.decodeRegion(new Rect(0, 0, width, height), options);
                if (bitmap == null) {
                    bitmap = BitmapFactory.decodeFile(mPath, options);
                }
                duration = (int) (System.currentTimeMillis() - time);
                FetcherHolder.getPreviewBitmapCache().addBitmapToCache(mPath, bitmap, true, duration > 100);
            } else {
                FetcherHolder.getPreviewBitmapCache().addBitmapToCache(mPath, bitmap, true, false);
            }
            if (mListener != null) {
                mListener.onDecodeOver(bitmap, width, height, decoder);
            }
        }
    };

    public BitmapRegionDecoder mDecoder;

    private DecodeListener mListener;

    public PreViewBitmap(DecodeListener listener, DecoderLoader loader) {
        mLoader = loader;
        mBitmapRect = new Rect();
        mListener = listener;
        mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
    }

    public PreViewBitmap(String path, DecodeListener listener, DecoderLoader loader) {
        mLoader = loader;
        mBitmapRect = new Rect();
        mListener = listener;
        update(path);
        mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
    }

    @Override
    public void draw(Canvas canvas, Rect source, RectF target) {
        if (mScreenBitmap != null && !mScreenBitmap.isRecycled()) {
            canvas.drawBitmap(mScreenBitmap, source, target, mPaint);
        }
    }

    @Override
    public void draw(Canvas canvas, Matrix matrix) {
        if (mScreenBitmap != null && !mScreenBitmap.isRecycled()) {
            canvas.drawBitmap(mScreenBitmap, matrix, mPaint);
        }
    }

    public static interface DecodeListener {
        public void onDecodeOver(Bitmap bitmap, int width, int height, BitmapRegionDecoder decoder);
    }

    public static abstract class PreViewBitmapJob<T> implements ThreadPool.Job<T> {
        public String path;
    }

    /**
     * 在UI线程上执行
     *
     * @param bitmap
     */
    public void setBitmap(Bitmap bitmap) {
        mScreenBitmap = bitmap;
        mBitmapRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
    }

    public void setDecoder(BitmapRegionDecoder decoder) {
        mDecoder = decoder;
    }

    public void update(String path) {
        mPath = path;
        if (mTask != null) {
            mTask.cancel();
        }
        recycle();
        mJob.path = path;
        mTask = mLoader.loadDecoderAndBitmap(mJob, mFutureListener);
    }

    public void reload() {
        if (mTask != null && mJob.path.equals(mPath)) {//正确的任务正在执行 不需要重新创建

        } else {//任务不正确 或者 任务不存在
            if (mTask != null) {
                mTask.cancel();
            }
            mJob.path = mPath;
            mTask = mLoader.loadDecoderAndBitmap(mJob, mFutureListener);
        }
    }

    @Override
    public void recycle() {
        /**
         * 有单例的缓存存在  先不进行手动回收 只是清除掉引用
         */
//		if(mScreenBitmap != null && !mScreenBitmap.isRecycled()){
//			mScreenBitmap.recycle();
//		}
//		if(mDecoder != null && !mDecoder.isRecycled()){
//			mDecoder.recycle();
//		}
        if (mTask != null) {
            mTask.cancel();
            mTask = null;
        }
        mScreenBitmap = null;
    }


    public int getWidth() {
        return mBitmapRect.width();
    }

    public int getHeight() {
        return mBitmapRect.height();
    }

    public Bitmap getScreenBitmap() {
        return mScreenBitmap;
    }
}
